<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebRTC webcam - LiveTalking数字人交互平台</title>
    <!-- 引入jQuery 2.1.1 -->
    <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <!-- 引入SockJS 0.3.4 -->
    <script src="https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js"></script>
    <!-- 引入SRS SDK (WHEP播放器) -->
    <script src="https://ossrs.net/players/srsRtcPlayer-2.0.148.js"></script>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            background-size: 400% 400%;
            animation: gradientBG 15s ease infinite;
            color: #fff;
            line-height: 1.6;
            padding: 20px;
            min-height: 100vh;
        }
        
        @keyframes gradientBG {
            0% { background-position: 0% 50%; }
            50% { background-position: 100% 50%; }
            100% { background-position: 0% 50%; }
        }
        
        .container {
            max-width: 1280px;
            margin: 0 auto;
            background: rgba(0, 5, 30, 0.85);
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
            overflow: hidden;
            border: 1px solid rgba(100, 150, 255, 0.3);
        }
        
        header {
            background: linear-gradient(to right, #0f0c29, #302b63, #24243e);
            padding: 20px 30px;
            text-align: center;
            border-bottom: 1px solid #4a5fc2;
        }
        
        h1 {
            font-size: 2.2rem;
            margin-bottom: 10px;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
            background: linear-gradient(to right, #4facfe, #00f2fe);
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
        }
        
        .subtitle {
            color: #a0c8ff;
            font-size: 1.1rem;
            max-width: 800px;
            margin: 0 auto;
        }
        
        .content {
            padding: 25px;
            display: grid;
            grid-template-columns: 1fr;
            gap: 25px;
        }
        
        @media (min-width: 900px) {
            .content {
                grid-template-columns: 1fr 380px;
            }
        }
        
        .video-section {
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        
        .player-container {
            position: relative;
            border-radius: 12px;
            overflow: hidden;
            background: #000;
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
            aspect-ratio: 16/9;
        }
        
        #player {
            width: 100%;
            height: 100%;
            display: none;
            background: #000;
        }
        
        .player-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            background: linear-gradient(135deg, #0f0c29, #302b63);
            color: #fff;
            text-align: center;
            padding: 20px;
            transition: all 0.3s ease;
        }
        
        .player-overlay h2 {
            font-size: 1.8rem;
            margin-bottom: 15px;
            color: #4facfe;
        }
        
        .player-overlay p {
            max-width: 600px;
            margin-bottom: 25px;
            color: #c0d6ff;
            line-height: 1.7;
        }
        
        .controls {
            display: flex;
            flex-wrap: wrap;
            gap: 15px;
            align-items: center;
        }
        
        .stun-config {
            flex: 1;
            min-width: 200px;
        }
        
        .stun-config label {
            display: block;
            margin-bottom: 8px;
            color: #a0c8ff;
            font-weight: 500;
        }
        
        #stun-server {
            width: 100%;
            padding: 10px 12px;
            border-radius: 8px;
            border: 1px solid #4a5fc2;
            background: rgba(10, 20, 50, 0.7);
            color: #fff;
            font-size: 1rem;
            transition: border-color 0.3s;
        }
        
        #stun-server:focus {
            outline: none;
            border-color: #4facfe;
            box-shadow: 0 0 0 2px rgba(79, 172, 254, 0.3);
        }
        
        #start-btn {
            background: linear-gradient(to right, #4facfe, #00f2fe);
            color: #0f0c29;
            border: none;
            border-radius: 8px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            padding: 8px 16px;
            font-size: 1.1rem;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
        }
        
        #start-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
            filter: brightness(1.05);
        }
        
        #start-btn:active {
            transform: translateY(0);
        }
        
        #start-btn[disabled] {
            background: #555;
            cursor: not-allowed;
            transform: none;
            box-shadow: none;
        }
        
        .status-indicator {
            display: inline-flex;
            align-items: center;
            gap: 8px;
            padding: 8px 15px;
            border-radius: 20px;
            background: rgba(0, 0, 0, 0.3);
            font-size: 0.95rem;
        }
        
        .status-dot {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background: #ff4757;
        }
        
        .status-dot.connected {
            background: #2ed573;
            box-shadow: 0 0 8px #2ed573;
        }
        
        .status-dot.connecting {
            background: #ffa502;
            animation: pulse 1.5s infinite;
        }
        
        @keyframes pulse {
            0% { box-shadow: 0 0 0 0 rgba(255, 165, 2, 0.7); }
            70% { box-shadow: 0 0 0 10px rgba(255, 165, 2, 0); }
            100% { box-shadow: 0 0 0 0 rgba(255, 165, 2, 0); }
        }
        
        .chat-section {
            background: rgba(10, 20, 50, 0.6);
            border-radius: 12px;
            padding: 20px;
            display: flex;
            flex-direction: column;
            height: 100%;
            border: 1px solid rgba(100, 150, 255, 0.2);
        }
        
        .chat-header {
            display: flex;
            align-items: center;
            gap: 10px;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 1px solid rgba(100, 150, 255, 0.3);
        }
        
        .chat-header h2 {
            color: #4facfe;
            font-size: 1.4rem;
        }
        
        .digital-avatar {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            background: linear-gradient(135deg, #4facfe, #00f2fe);
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            color: #0f0c29;
        }
        
        .chat-messages {
            flex: 1;
            overflow-y: auto;
            padding: 10px 0;
            max-height: 300px;
            min-height: 200px;
            background: rgba(0, 5, 30, 0.7);
            border-radius: 10px;
            padding: 15px;
            margin-bottom: 15px;
            border: 1px solid rgba(100, 150, 255, 0.2);
        }
        
        .message {
            margin-bottom: 12px;
            padding: 10px 15px;
            border-radius: 18px;
            max-width: 85%;
            line-height: 1.5;
        }
        
        .user-message {
            background: linear-gradient(to right, #4facfe, #00f2fe);
            color: #0f0c29;
            margin-left: auto;
            border-bottom-right-radius: 5px;
        }
        
        .system-message {
            background: rgba(100, 150, 255, 0.2);
            color: #c0d6ff;
            margin-right: auto;
            border-bottom-left-radius: 5px;
        }
        
        .chat-input {
            display: flex;
            gap: 10px;
        }
        
        #message-input {
            flex: 1;
            padding: 12px 15px;
            border-radius: 8px;
            border: 1px solid #4a5fc2;
            background: rgba(10, 20, 50, 0.7);
            color: #fff;
            font-size: 1rem;
        }
        
        #message-input:focus {
            outline: none;
            border-color: #4facfe;
        }
        
        #send-btn {
            background: linear-gradient(to right, #4facfe, #00f2fe);
            color: #0f0c29;
            border: none;
            border-radius: 8px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            padding: 8px 16px;
            font-size: 1rem;
        }
        
        #send-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
        }
        
        #send-btn:active {
            transform: translateY(0);
        }
        
        #send-btn[disabled] {
            background: #555;
            cursor: not-allowed;
        }
        
        .error-message {
            background: #ff4757;
            color: white;
            padding: 15px;
            border-radius: 8px;
            margin-top: 15px;
            display: none;
            animation: fadeIn 0.3s;
        }
        
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(-10px); }
            to { opacity: 1; transform: translateY(0); }
        }
        
        footer {
            text-align: center;
            padding: 20px;
            color: #a0c8ff;
            font-size: 0.9rem;
            border-top: 1px solid rgba(100, 150, 255, 0.2);
            margin-top: 10px;
        }
        
        .connection-info {
            background: rgba(0, 0, 0, 0.2);
            border-radius: 8px;
            padding: 12px;
            margin-top: 15px;
            font-size: 0.9rem;
        }
        
        .info-item {
            display: flex;
            justify-content: space-between;
            margin-bottom: 6px;
        }
        
        .info-label {
            color: #a0c8ff;
            font-weight: 500;
        }
        
        @media (max-width: 768px) {
            .controls {
                flex-direction: column;
            }
            
            .stun-config {
                width: 100%;
            }
            
            h1 {
                font-size: 1.8rem;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>WebRTC webcam</h1>
            <p class="subtitle">LiveTalking数字人交互平台 - 实时音视频交互与文本对话</p>
        </header>
        
        <div class="content">
            <div class="video-section">
                <div class="player-container">
                    <video id="player" autoplay playsinline></video>
                    <div class="player-overlay" id="player-overlay">
                        <h2>LiveTalking 数字人交互</h2>
                        <p>点击下方"Start"按钮开始实时视频交互，与AI数字人进行自然对话。系统将使用WebRTC技术提供低延迟音视频体验。</p>
                        <div class="controls">
                            <div class="stun-config">
                                <label for="stun-server">STUN服务器</label>
                                <select id="stun-server">
                                    <option value="">自动选择 (推荐)</option>
                                    <option value="stun:stun.l.google.com:19302">Google STUN 服务器</option>
                                    <option value="stun:global.stun.twilio.com:3478?transport=udp">Twilio STUN 服务器</option>
                                    <option value="stun:stun.services.mozilla.com">Mozilla STUN 服务器</option>
                                </select>
                            </div>
                            <button id="start-btn">Start</button>
                        </div>
                    </div>
                </div>
                
                <div class="status-indicator">
                    <span class="status-dot" id="connection-status"></span>
                    <span id="status-text">等待连接...</span>
                </div>
                
                <div class="connection-info" id="connection-info" style="display:none;">
                    <div class="info-item">
                        <span class="info-label">服务器地址:</span>
                        <span id="server-address">http://<span id="hostname">localhost</span>:1985/rtc/v1/whep/</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">流名称:</span>
                        <span>live/livestream</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">连接状态:</span>
                        <span id="connection-state">未连接</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">延迟:</span>
                        <span id="latency">-- ms</span>
                    </div>
                </div>
                
                <div class="error-message" id="error-message">
                    连接失败: 无法建立WebRTC连接，请检查网络或STUN服务器设置
                </div>
            </div>
            
            <div class="chat-section">
                <div class="chat-header">
                    <div class="digital-avatar">AI</div>
                    <h2>数字人对话</h2>
                </div>
                
                <div class="chat-messages" id="chat-messages">
                    <div class="message system-message">
                        您好！我是LiveTalking数字人助手，已准备好与您进行实时音视频交互。点击"Start"按钮开始体验吧！
                    </div>
                </div>
                
                <div class="chat-input">
                    <input type="text" id="message-input" placeholder="输入您的消息..." disabled>
                    <button id="send-btn" disabled>发送</button>
                </div>
            </div>
        </div>
        
        <footer>
            LiveTalking 数字人交互平台 &copy; 2023 | 基于 WebRTC 和 SRS 实时流媒体技术
        </footer>
    </div>

    <script>
        $(document).ready(function() {
            // 全局变量
            let player = null;
            let sock = null;
            let connectionState = 'disconnected'; // disconnected, connecting, connected, error
            let wsConnected = false;
            
            // 设置当前主机名
            const hostname = window.location.hostname || 'localhost';
            $('#hostname').text(hostname);
            
            // 初始化
            function init() {
                updateConnectionState('disconnected');
                updateStatus('等待连接...', 'disconnected');
                $('#message-input').prop('disabled', true);
                $('#send-btn').prop('disabled', true);
                $('#player').hide();
                $('#player-overlay').show();
                $('#connection-info').hide();
                $('#error-message').hide();
            }
            
            // 更新连接状态
            function updateConnectionState(state) {
                connectionState = state;
                $('#connection-state').text(
                    state === 'connected' ? '已连接' :
                    state === 'connecting' ? '连接中...' :
                    state === 'error' ? '连接错误' : '未连接'
                );
                
                // 更新状态指示器
                const statusDot = $('#connection-status');
                statusDot.removeClass('connected connecting');
                if (state === 'connected') {
                    statusDot.addClass('connected');
                } else if (state === 'connecting') {
                    statusDot.addClass('connecting');
                }
            }
            
            // 更新状态文本
            function updateStatus(text, type) {
                $('#status-text').text(text);
                
                if (type === 'error') {
                    $('#error-message').text(text).show();
                    setTimeout(() => {
                        $('#error-message').fadeOut(500);
                    }, 5000);
                } else {
                    $('#error-message').hide();
                }
            }
            
            // 开始播放
            function startPlay() {
                if (connectionState === 'connecting' || connectionState === 'connected') {
                    return;
                }
                
                updateConnectionState('connecting');
                updateStatus('正在建立WebRTC连接...', 'info');
                $('#start-btn').prop('disabled', true).text('连接中...');
                
                // 获取STUN服务器配置
                const stunServer = $('#stun-server').val();
                const iceServers = [];
                
                if (stunServer) {
                    iceServers.push({ urls: stunServer });
                } else {
                    // 默认STUN服务器
                    iceServers.push({ 
                        urls: [
                            'stun:stun.l.google.com:19302',
                            'stun:global.stun.twilio.com:3478?transport=udp'
                        ]
                    });
                }
                
                // SRS WHEP 播放器配置
                const url = `http://${hostname}:1985/rtc/v1/whep/?app=live&stream=livestream`;
                const config = {
                    video: document.getElementById('player'),
                    url: url,
                    iceServers: iceServers,
                    api: url,
                    schema: 'http://',
                    port: 1985,
                    app: 'live',
                    stream: 'livestream',
                    rtc: {
                        // 降低延迟的配置
                        offerToReceiveAudio: 1,
                        offerToReceiveVideo: 1,
                        iceCandidatePoolSize: 0
                    }
                };
                
                try {
                    // 创建播放器实例
                    player = new SrsRtcPlayerAsync();
                    
                    // 设置事件监听
                    player.onconnect = function() {
                        console.log('Player connected');
                        updateConnectionState('connected');
                        updateStatus('WebRTC连接已建立', 'success');
                        $('#player').show();
                        $('#player-overlay').hide();
                        $('#connection-info').show();
                        $('#start-btn').text('已连接').prop('disabled', true);
                        
                        // 启用聊天功能
                        $('#message-input').prop('disabled', false);
                        $('#send-btn').prop('disabled', false);
                        
                        // 连接WebSocket
                        connectWebSocket();
                    };
                    
                    player.onplay = function() {
                        console.log('Player started playing');
                    };
                    
                    player.onerror = function(error) {
                        console.error('Player error:', error);
                        handlePlayerError(error);
                    };
                    
                    // 开始播放
                    player.play(config).then(function() {
                        console.log('Player started successfully');
                    }).catch(function(error) {
                        console.error('Player play error:', error);
                        handlePlayerError(error);
                    });
                    
                } catch (error) {
                    console.error('Player initialization error:', error);
                    handlePlayerError(error);
                }
            }
            
            // 处理播放器错误
            function handlePlayerError(error) {
                updateConnectionState('error');
                
                let errorMessage = 'WebRTC连接失败';
                if (error.message) {
                    errorMessage += ': ' + error.message;
                } else if (typeof error === 'string') {
                    errorMessage += ': ' + error;
                }
                
                updateStatus(errorMessage, 'error');
                $('#start-btn').prop('disabled', false).text('Start');
                
                // 显示错误消息
                $('#error-message').text(errorMessage).show();
                
                // 添加系统消息
                addChatMessage('系统', errorMessage, 'system');
            }
            
            // 连接WebSocket
            function connectWebSocket() {
                const wsUrl = `ws://${hostname}:8000/humanecho`;
                
                try {
                    sock = new SockJS(wsUrl);
                    
                    sock.onopen = function() {
                        console.log('WebSocket connected');
                        wsConnected = true;
                        addChatMessage('系统', '已建立文本消息连接', 'system');
                    };
                    
                    sock.onmessage = function(e) {
                        console.log('WebSocket message:', e.data);
                        addChatMessage('数字人', e.data, 'system');
                    };
                    
                    sock.onclose = function() {
                        console.log('WebSocket disconnected');
                        wsConnected = false;
                        if (connectionState === 'connected') {
                            addChatMessage('系统', '文本消息连接已断开', 'system');
                        }
                    };
                    
                    sock.onerror = function(error) {
                        console.error('WebSocket error:', error);
                        if (connectionState === 'connected') {
                            addChatMessage('系统', '文本消息连接错误', 'system');
                        }
                    };
                } catch (error) {
                    console.error('WebSocket connection error:', error);
                    addChatMessage('系统', '无法建立文本消息连接', 'system');
                }
            }
            
            // 发送消息
            function sendMessage() {
                const message = $('#message-input').val().trim();
                if (!message || !wsConnected || !sock) return;
                
                try {
                    sock.send(message);
                    addChatMessage('您', message, 'user');
                    $('#message-input').val('');
                } catch (error) {
                    console.error('Failed to send message:', error);
                    addChatMessage('系统', '消息发送失败', 'system');
                }
            }
            
            // 添加聊天消息
            function addChatMessage(sender, text, type) {
                const messagesContainer = $('#chat-messages');
                const messageClass = type === 'user' ? 'user-message' : 'system-message';
                
                const messageElement = `
                    <div class="message ${messageClass}">
                        ${type === 'user' ? '' : `<strong>${sender}:</strong> `}${text}
                    </div>
                `;
                
                messagesContainer.append(messageElement);
                messagesContainer.scrollTop(messagesContainer[0].scrollHeight);
            }
            
            // 事件绑定
            $('#start-btn').click(startPlay);
            
            $('#send-btn').click(sendMessage);
            
            $('#message-input').keypress(function(e) {
                if (e.which === 13) { // Enter key
                    sendMessage();
                }
            });
            
            // 模拟延迟测量
            function simulateLatency() {
                if (connectionState === 'connected') {
                    const latency = Math.floor(50 + Math.random() * 100);
                    $('#latency').text(latency + ' ms');
                }
                setTimeout(simulateLatency, 2000);
            }
            
            // 初始化
            init();
            simulateLatency();
            
            // 添加示例消息（开发用）
            setTimeout(() => {
                if (connectionState === 'disconnected') {
                    addChatMessage('系统', '提示：点击"Start"按钮开始实时音视频交互', 'system');
                }
            }, 2000);
        });
    </script>
</body>
</html>
